编程之美---数组循环移位

设计一个算法,把一个含有N个元素的数组循环右移K位,要求时间复杂度为 O(N), 且只允许使用两个附加变量。

解法一:

简单的办法是,每次将数组中的元素右移一位,循环K次。abcd1234 -> 4abcd123 -> 34abcd12。

代码如下:

public static void rightShift(int[] array, int len, int k){
        while(k > 0){
            int temp = array[len-1];
            for(int i = len-1; i > 0; i--){
                array[i] = array[i-1];
            }
            array[0] = temp;
            k--;
        }
    }

算法的时间复杂度为 O(K*N)。
当K是一个远大于N的数时,上面的解法就需要改进了。当 k=50000000时,移位所需要的时间如下:
这里写图片描述

解法二:

观察循环右移的特点后,发现每个元素右移N位后,都会回到原来的位置,因此右移 K 位跟右移 k%N 位的结果是一样的,算法改进如下:

public static void rightShift(int[] array, int len, int k){
        k %= len;
        while(k > 0){
            int temp = array[len-1];
            for(int i = len-1; i > 0; i--){
                array[i] = array[i-1];
            }
            array[0] = temp;
            k--;
        }
    }

解法三:

假设原数组为12345678,循环右移4位后变为56781234。其中 5678 和 1234的顺序是不变的,可以将这两段当做整体,右移K位就是将这两段的顺序交换。

  1. 逆序排列 1234: 12345678 -> 43215678
  2. 逆序排列 5678: 43215678 -> 43218765;
  3. 整体逆序: 43218765 -> 56781234。

代码如下:

public static void reverse(int[] array, int start, int end){
        for(; start < end; start++, end--){
            int temp = array[end];
            array[end] = array[start];
            array[start] = temp;
        }
    }

    public static void rightShift(int[] array, int len, int k){
        k %= len;
        reverse(array, 0, len-k-1);
        reverse(array, len-k, len-1);
        reverse(array, 0, len-1);
    }

当k=50000000时,所花时间如下:
这里写图片描述

可以看到效率有了明显提升。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值